﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DiagramDesigner
{
    /// <summary>
    /// Interaction logic for AngleMeasure.xaml
    /// </summary>
    public partial class AngleMeasure : UserControl
    {
        public AngleMeasure()
        {
            InitializeComponent();
        }


        public Point SubstratePt1
        {
            get { return (Point)GetValue(SubstratePt1Property); }
            set { SetValue(SubstratePt1Property, value); }
        }

        // Using a DependencyProperty as the backing store for SubstratePt1.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SubstratePt1Property =
            DependencyProperty.Register("SubstratePt1", typeof(Point), typeof(AngleMeasure),
            new UIPropertyMetadata(new Point(0,0), BaseLinePointChangedCallback));

        public Point SubstratePt2
        {
            get { return (Point)GetValue(SubstratePt2Property); }
            set { SetValue(SubstratePt2Property, value); }
        }

        // Using a DependencyProperty as the backing store for SubstratePt2.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SubstratePt2Property =
            DependencyProperty.Register("SubstratePt2", typeof(Point), typeof(AngleMeasure),
            new UIPropertyMetadata(new Point(0, 0), BaseLinePointChangedCallback));


        public Point AngleLeftPtFree
        {
            get { return (Point)GetValue(AngleLeftPtFreeProperty); }
            set { SetValue(AngleLeftPtFreeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AngleLeftPt1ty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AngleLeftPtFreeProperty =
            DependencyProperty.Register("AngleLeftPtFree", typeof(Point), typeof(AngleMeasure), new UIPropertyMetadata(new Point(0, 0)));


        public Point AngleLeftPtBound
        {
            get { return (Point)GetValue(AngleLeftPtBoundProperty); }
            set { SetValue(AngleLeftPtBoundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AngleLeftPt2.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AngleLeftPtBoundProperty =
            DependencyProperty.Register("AngleLeftPtBound", typeof(Point), typeof(AngleMeasure),
            new FrameworkPropertyMetadata(new Point(0, 0), null, CoerceAngleLeftPtBoundCallback));



        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Stroke.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StrokeProperty =
            DependencyProperty.Register("Stroke", typeof(Brush), typeof(AngleMeasure), new UIPropertyMetadata(null));



        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        // Using a DependencyProperty as the backing store for StrokeThickness.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StrokeThicknessProperty =
            DependencyProperty.Register("StrokeThickness", typeof(double), typeof(AngleMeasure), new UIPropertyMetadata(1.0));


        private static void BaseLinePointChangedCallback(DependencyObject obj,
           DependencyPropertyChangedEventArgs e)
        {
            AngleMeasure _this = (AngleMeasure)obj;

            //if (!_this.SubstratePt1.HasValue || !_this.SubstratePt2.HasValue)
            //    return;

            //if (_this.AngleLeftPtBound.HasValue && _this.AngleLeftPtFree.HasValue)
            _this.AngleLeftPtBound = _this.AdjustStart(_this.AngleLeftPtBound, _this.SubstratePt1, _this.SubstratePt2);
        }

        private static object CoerceAngleLeftPtBoundCallback(DependencyObject obj,
           object val)
        {
            AngleMeasure _this = (AngleMeasure)obj;
            Point p = (Point)val;

            //if (!_this.SubstratePt1.HasValue ||
            //    !_this.SubstratePt2.HasValue ||
            //    !_this.AngleLeftPtFree.HasValue ||
            //    !_this.AngleLeftPtBound.HasValue)
            //    return p;

            Point pnew = _this.AdjustStart(p, _this.SubstratePt1, _this.SubstratePt2);
            return pnew;

        }

        protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters)
        {
            //hitTestParameters.
            return base.HitTestCore(hitTestParameters);
        }
        private Point AdjustStart(Point p, Point p1, Point p2)
        {            
            //find StartPoint projection onto the substrate
            double fDenominator = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y);

            if (fDenominator == 0) // p1 and p2 are the same
                return p1;

            double t = (p.X * (p2.X - p1.X) - (p2.X - p1.X) * p1.X + p.Y * (p2.Y - p1.Y) - (p2.Y - p1.Y) * p1.Y) / fDenominator;
            if (t < 0)
                t = 0;
            if (t > 1)
                t = 1;

            return new Point(p1.X + (p2.X - p1.X) * t, p1.Y + (p2.Y - p1.Y) * t);
        }
        
    }
}
